package com.xinyan.service.impl;

import com.github.xingshuangs.iot.protocol.s7.serializer.S7Serializer;
import com.github.xingshuangs.iot.protocol.s7.service.MultiAddressWrite;
import com.github.xingshuangs.iot.protocol.s7.service.S7PLC;

import com.xinyan.dto.ListPageParam;
import com.xinyan.dto.ReadPlcParam;
import com.xinyan.dto.WriteMultiPLCParam;
import com.xinyan.dto.WritePLcParam;
import com.xinyan.plc.*;
import com.xinyan.service.MachineService;
import com.xinyan.vo.PLCReadResult;
import com.xinyan.vo.R;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;

@Service
public class MachineServiceImpl implements MachineService {

    @Autowired
    private Map<Integer, S7PLC> s7PLCMap;

    @Autowired
    private HandAutoParam handAutoParam;

    @Autowired
    private HandModeStartAndStop handModeStartAndStop;

    @Value("${plc.status}")
    private String plcStatus;

    @Override
    public List<PLCReadResult<Boolean>> readBoolean(List<ReadPlcParam> params) {
        List<PLCReadResult<Boolean>> list = new ArrayList<>();
        params.forEach(param -> {
            Integer id = param.getId();
            List<String> addrs = param.getAddrs();
            S7PLC s7PLC = s7PLCMap.get(id);
            list.add(new PLCReadResult<>(id, s7PLC.readBoolean(addrs)));
        });
        return list;
    }

    @Override
    public void writeBoolean(WritePLcParam<Boolean> params) {
        Integer id = params.getId();
        S7PLC s7PLC = s7PLCMap.get(id);
        s7PLC.writeBoolean(params.getAddrs().get(0), params.getList().get(0));
    }

    @Override
    public void writeMultiBool(WriteMultiPLCParam<Boolean> params) {
        List<WritePLcParam> writePLcParam = params.getWritePLcParam();
        writePLcParam.forEach(e -> {
            List<Boolean> list = e.getList();
            List<String> addrs = e.getAddrs();
            Integer id = e.getId();
            S7PLC s7PLC = s7PLCMap.get(id);
            MultiAddressWrite multiAddressWrite = new MultiAddressWrite();
            for (int i = 0; i < list.size(); i++) {
                multiAddressWrite.addBoolean(addrs.get(i), list.get(i));
            }
            s7PLC.writeMultiData(multiAddressWrite);
        });
    }

    @Override
    public void hand(List<Integer> ids) {
        ids.forEach(id -> {
            S7PLC s7PLC = s7PLCMap.get(id);
            S7Serializer s7Serializer = S7Serializer.newInstance(s7PLC);
            handAutoParam.setM32(true);
            handAutoParam.setM33(false);
            s7Serializer.write(handAutoParam);
        });
    }


    @Override
    public void auto(List<Integer> ids) {
        ids.forEach(id -> {
            S7PLC s7PLC = s7PLCMap.get(id);
            S7Serializer s7Serializer = S7Serializer.newInstance(s7PLC);
            handAutoParam.setM32(false);
            handAutoParam.setM33(true);
            s7Serializer.write(handAutoParam);
        });
    }

    @Override
    public List<Integer> handStart(List<Integer> ids) {
        List<Integer> list = new ArrayList<>();
        ids.forEach(id -> {
            // 判断是否在手动模式下
            S7PLC s7PLC = s7PLCMap.get(id);
            if (s7PLC.readBoolean("m3.2")) {
                S7Serializer s7Serializer = S7Serializer.newInstance(s7PLC);
                handModeStartAndStop.setM41(true);
                handModeStartAndStop.setM42(false);
                s7Serializer.write(handModeStartAndStop);
                list.add(id);
            }
        });
        return list;
    }

    @Override
    public List<Integer> handStop(List<Integer> ids) {
        List<Integer> list = new ArrayList<>();
        ids.forEach(id -> {
            // 判断是否在手动模式下
            S7PLC s7PLC = s7PLCMap.get(id);
            if (s7PLC.readBoolean("m3.2")) {
                S7Serializer s7Serializer = S7Serializer.newInstance(s7PLC);
                handModeStartAndStop.setM41(false);
                handModeStartAndStop.setM42(true);
                s7Serializer.write(handModeStartAndStop);
                list.add(id);
            }
        });
        return list;
    }


    @Override
    public void setFrequency(List<Integer> ids, float frequency) {
        ids.forEach(id -> {
            S7PLC s7PLC = s7PLCMap.get(id);
            s7PLC.writeFloat32("vd150", frequency);
        });
    }

    @Override
    public List<RunParam> readRunParam(List<Integer> ids) {
        List<RunParam> list = new ArrayList<>();
        ids.forEach(id -> {
            S7PLC s7PLC = s7PLCMap.get(id);
            S7Serializer s7Serializer = S7Serializer.newInstance(s7PLC);
            RunParam runParam = s7Serializer.read(RunParam.class);
            list.add(runParam);
        });
        return list;
    }


    @Override
    public RunParam readRunParamById(int id) {
        S7PLC s7PLC = s7PLCMap.get(id);
        S7Serializer s7Serializer = S7Serializer.newInstance(s7PLC);
        RunParam runParam = s7Serializer.read(RunParam.class);


        if ("dev".equals(plcStatus)) {
            Random random = new Random();
            runParam = new RunParam();
            runParam.setVw118(random.nextInt(50) + 1000);
            runParam.setVd400((float) (random.nextInt(45) + 5.0));
            runParam.setVd404((float) (random.nextInt(3) + 10.0));
            runParam.setVd408((float) (random.nextInt(80) + 300.0));
            runParam.setVd412((float) (Math.round(random.nextFloat() * 10) / 10.0 + 70.0));
            runParam.setVd416((float) (Math.round(random.nextFloat() * 10) / 10.0 + 4.5));
        }
        return runParam;
    }

    @Override
    public IndexParam readIndexParam(int id) {
        S7PLC s7PLC = s7PLCMap.get(id);
        S7Serializer s7Serializer = S7Serializer.newInstance(s7PLC);
        IndexParam indexParam = s7Serializer.read(IndexParam.class);
        return indexParam;
    }

    @Override
    public List<RepeatParam> readRepeatParam(List<Integer> ids) {
        List<RepeatParam> list = new ArrayList<>();
        ids.forEach(id -> {
            S7PLC s7PLC = s7PLCMap.get(id);
            S7Serializer s7Serializer = S7Serializer.newInstance(s7PLC);
            RepeatParam repeatParam = s7Serializer.read(RepeatParam.class);
            repeatParam.getRealVal();
            list.add(repeatParam);
        });
        return list;
    }

    @Override
    public RepeatParam readRepeatParamById(int i) {
        S7PLC s7PLC = s7PLCMap.get(i);
        S7Serializer s7Serializer = S7Serializer.newInstance(s7PLC);
        RepeatParam repeatParam = s7Serializer.read(RepeatParam.class);
        repeatParam.getRealVal();
        return repeatParam;
    }

    @Override
    public List<Integer> setRepeatParam(RepeatRunStopParam repeatRunStopParam) {
        List<Integer> ids = repeatRunStopParam.getIds();
        List<Integer> list = new ArrayList<>();
        ids.forEach(id -> {
            S7PLC s7PLC = s7PLCMap.get(id);
            s7PLC.writeByte(repeatRunStopParam.getAddr(), repeatRunStopParam.getVal());
            list.add(id);
        });
        return list;
    }


    @Override
    public List<Integer> writeRepeatParam(Map<Integer, RepeatParam> map) {
        List<Integer> list = new ArrayList<>();
        map.keySet().forEach(key -> {
            S7PLC s7PLC = s7PLCMap.get(key);
            S7Serializer s7Serializer = S7Serializer.newInstance(s7PLC);
            s7Serializer.write(map.get(key));
            list.add(key);
        });
        return list;
    }


    @Override
    public void writeRepeatParamByEntity(RepeatParam repeatParam, int id) {
        // 自动模式下运行持续时间-分钟
        repeatParam.setVb500(new byte[]{Byte.valueOf(repeatParam.getVb500_0())});
        // 自动模式下运行持续时间-秒
        repeatParam.setVb501(new byte[]{Byte.valueOf(repeatParam.getVb501_0())});
        // 自动模式下停止持续时间-分钟
        repeatParam.setVb502(new byte[]{Byte.valueOf(repeatParam.getVb502_0())});
        // 自动模式下停止持续时间-秒
        repeatParam.setVb503(new byte[]{Byte.valueOf(repeatParam.getVb503_0())});
        S7PLC s7PLC = s7PLCMap.get(id);
        S7Serializer s7Serializer = S7Serializer.newInstance(s7PLC);
        s7Serializer.write(repeatParam);
    }

    @Override
    public ListPageParam readListPageParam(int id) {
        S7PLC s7PLC = s7PLCMap.get(id);
        S7Serializer s7Serializer = S7Serializer.newInstance(s7PLC);
        ListPageParam pageParam = s7Serializer.read(ListPageParam.class);
        return pageParam;
    }
}
